//
// Created by 12345 on 2025/2/19.
//


#include "connect_manager.h"


ConnectManager *ConnectManager::getInstance() {
    static ConnectManager instance;
    return &instance;
}

void ConnectManager::init() {
    //初始化失败退出应用
    if (!initUdp()) {
        std::terminate();
    }
    //保持心跳
    keepHeart();
    //检查是否有report数据来判断上下线
    keepStatusCheck();
    //定时发送控制信息
    keepCommand();


//    Gazella::GzTimer::create_timer([](const std::shared_ptr<Gazella::ITimerCallbackArg> &) {
//        auto payload = CommandBean::getInstance()->build();
//        DeviceAgentModel::DeviceAgentProperty cmd;
//        CommandBean::getInstance()->forceCode(cmd, cmd);
//        mp_log_info(DEFAULT_LOGGER, "forceCode");
//
//        Gazella::GzTimer::create_timer([](const std::shared_ptr<Gazella::ITimerCallbackArg> &) {
//            auto payload = CommandBean::getInstance()->build();
//            DeviceAgentModel::DeviceAgentProperty cmd;
//            CommandBean::getInstance()->standSitCode(cmd, cmd);
//            mp_log_info(DEFAULT_LOGGER, "standSitCode");
//        },nullptr,2);

//    },nullptr, 5, 5);
}

bool ConnectManager::initUdp() {
    if (commandClient.init(remoteAddr, commandPort) != 0) {
        return false;
    }
    if (heartClient.init(remoteAddr, heartPort)) {
        return false;
    }
    if (agentServer.init(localAddr, localReportPort) != 0) {
        return false;
    }
    agentServer.add_recv_over_callback([&](const std::string &remote_host, int remote_port, std::string &msg) {
        parseReport(remote_host, remote_port, msg);
    });
    return true;
}


void ConnectManager::keepHeart() {
    taskCache.push_back(std::make_shared<std::thread>([&](){
        while (true){
            std::string buffer;
            buffer.push_back(static_cast<char>(0x5A));
            buffer.push_back(static_cast<char>(0xA5));
            buffer.push_back(static_cast<char>(0x09));
            buffer.push_back(static_cast<char>(0xA5));
            buffer.push_back(static_cast<char>(0x01));
            buffer.push_back(static_cast<char>(0x55));
            buffer.push_back(static_cast<char>(0x00));
            int temp = (0xA5 + 0x01 + 0x55);
            char byte7 = static_cast<char>(temp & 0x000000ff);
            buffer.push_back(byte7);
            buffer.push_back(static_cast<char>(0xff));
            mp_log_info(DEFAULT_LOGGER, "send_heart:%s", coverHex(buffer).c_str());
            heartClient.send_message(buffer);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }));

//    //定时发送心跳包给狗
//    auto sendHeartTask = [&](const std::shared_ptr<Gazella::ITimerCallbackArg> &) {
//
//    };
//    Gazella::GzTimer::create_timer(
//            std::function<void(std::shared_ptr<Gazella::ITimerCallbackArg>)>(sendHeartTask),
//            nullptr, 0,0.1
//    );
}


void ConnectManager::keepCommand() {
//    auto timerCallback = [&](const std::shared_ptr<Gazella::ITimerCallbackArg> &) {
//        auto payload = CommandBean::getInstance()->build();
//        commandClient.send_message(payload);
//        CommandBean::getInstance()->reset();
//        mp_log_info(DEFAULT_LOGGER, "send_command:%s", coverHex(payload).c_str());
//    };
//    Gazella::GzTimer::create_timer(
//            std::function<void(std::shared_ptr<Gazella::ITimerCallbackArg>)>(timerCallback),
//            nullptr, 0,0.02
//    );

    taskCache.push_back(std::make_shared<std::thread>([&](){
        while (true){
            auto payload = CommandBean::getInstance()->build();
            commandClient.send_message(payload);
            CommandBean::getInstance()->reset();
            mp_log_info(DEFAULT_LOGGER, "send_command:%s", coverHex(payload).c_str());
            std::this_thread::sleep_for(std::chrono::milliseconds(ConfigModel::getInstance()->sendTime));
        }
    }));

}


void ConnectManager::parseReport(const std::string &remote_host, int remote_port, std::string &msg) {
    if (!checkHead(msg)) {
        return;
    }
    ReportBean::getInstance().parse(msg);
    receiveReportTime = std::chrono::system_clock::now();
}

bool ConnectManager::checkHead(std::string &msg) {
    if (msg.size() < 69) {
        return false;
    }
    if (static_cast<uint8_t>(msg[0]) == 0x5A && static_cast<uint8_t>(msg[1]) == 0xA4 &&
        static_cast<uint8_t>(msg[2]) == 0x44 && static_cast<uint8_t>(msg[68]) == 0xff) {
        return true;
    }
    return false;
}

void ConnectManager::keepStatusCheck() {
    auto checkHeartTask = [&](const std::shared_ptr<Gazella::ITimerCallbackArg> &) {
        auto curTime = std::chrono::duration_cast<std::chrono::seconds>(
                std::chrono::system_clock::now().time_since_epoch());
        auto preTimeSeconds = std::chrono::duration_cast<std::chrono::seconds>(receiveReportTime.time_since_epoch());
        auto diff = curTime - preTimeSeconds;
        DeviceAgentModel::DeviceAgentProperty statusProperty;
        Gazella::Daf::DafModel::get_instance()->get_property("status", statusProperty);
        if (diff.count() < 15) {
            mp_log_info(DEFAULT_LOGGER, "heart  online");
            statusProperty.mutable_property_int()->set_value(1);
        } else {
            mp_log_info(DEFAULT_LOGGER, "heart  offline");
            statusProperty.mutable_property_int()->set_value(2);
        }
        Gazella::Daf::DafModel::get_instance()->set_property("status", statusProperty);
    };

    Gazella::GzTimer::create_timer(
            std::function<void(std::shared_ptr<Gazella::ITimerCallbackArg>)>(checkHeartTask),
            nullptr, 0, 5
    );
}


